// file：arch/x86/hardware/cursor.c
// autor:jiangxinpeng
// time:2021.2.2
// copyright:(C) 2020-2050 by Jiang xinpeng. All rights reserved.

#include <arch/cursor.h>
#include <arch/io.h>
#include <lib/type.h>

// the file use to cursor control
uint16_t chars_per_page = MAXLINE * MAXLIST;

// init cursor
void InitCursor(int x, int y)
{
    SetCursor(x, y);
}

// set cursor to line and list (tip:line and list are start with 0)
void SetCursor(int x, int y)
{
    uint16_t position = 0;

    // check argument if is available
    if (x < MAXLINE)
    {
        if (y < MAXLIST)
        {
            // figure out cursor position in assiant line and list
            position = y * CHARS_PER_LINE + x;
            // write position data to cursor register
            WriteCursor(position);
            return;
        }
    }
}

// get current cursor info
void GetCursor(int x, int y)
{
    uint16_t position;

    position = ReadCursor();
    y = position / CHARS_PER_LINE;
    x = position % CHARS_PER_LINE;
}

// write position to cursor register
int WriteCursor(uint16_t position)
{
    if (position < MAXLINE * MAXLIST)
    {
        // use io port to access CRT register in order to set cursor
        // write cursor position low8bits
        Out8((uint16_t)CRT_ADDRESS_PORT, (uint8_t)CURSOR_POSITION_LOW8_PORT);
        Out8((uint16_t)CRT_DATA_POST, (uint8_t)position);
        // write cursor postion high8bits
        Out8((uint16_t)CRT_ADDRESS_PORT, (uint8_t)CURSOR_POSITON_HIGH8_PORT);
        Out8((uint16_t)CRT_DATA_POST, (uint8_t)(position >> 8));
        return 0;
    }
    return -1;
}

// read position from cursor register
uint16_t ReadCursor()
{
    uint16_t position;
    uint8_t low, high;

    // read cursor position low8bits
    Out8((uint16_t)CRT_ADDRESS_PORT,(uint8_t) CURSOR_POSITION_LOW8_PORT);
    low = In8(CRT_DATA_POST);
    // read cursor position high 8bits
    Out8((uint16_t)CRT_ADDRESS_PORT,(uint8_t) CURSOR_POSITON_HIGH8_PORT);
    high = In8((uint16_t)CRT_DATA_POST);
    // figure position
    position = (high << 8) | low;

    return position;
}
